package site.teamo.biu.net.common.util;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.Getter;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * @author haocongshun
 * @date 2023/02/28 14:12:55
 */
public class MultipleChannelTcpClient {

    private final String host;
    private final int port;

    private final Bootstrap bootstrap;

    private final ChannelGroup channels;

    @Getter
    private final long createTime;

    public MultipleChannelTcpClient(String host,
                                    int port,
                                    ChannelInitializer<SocketChannel> initializer,
                                    EventLoopGroup group,
                                    Consumer<Bootstrap> customConfig) {
        this.host = host;
        this.port = port;
        this.bootstrap = new Bootstrap()
                .group(group);
        //调用用户自定义配置，可以对bootstrap进行操作
        customConfig.accept(bootstrap);
        bootstrap.channel(NioSocketChannel.class)
                .handler(initializer);

        channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
        this.createTime = System.currentTimeMillis();
    }

    public void getNewChannel(Consumer<Channel> newChannel) {
        bootstrap.connect(host, port).addListener(
                (ChannelFutureListener) future -> {
                    if (future.isSuccess()) {
                        Channel channel = future.channel();
                        channels.add(channel);
                        try {
                            newChannel.accept(channel);
                        } catch (Exception e) {
                            //如果执行自定义的channel处理出现异常，则关闭当前channel，并从group中移除channel
                            channels.remove(channel);
                            channel.close();
                        }
                    } else {
                        Channel channel = future.channel();
                        if (channel != null) {
                            channel.close();
                        }
                    }
                }
        );
    }

    public int size() {
        return channels.size();
    }

    public void close() {
        channels.close();
    }

    public void clear() {
        Iterator<Channel> iterator = channels.iterator();
        while (iterator.hasNext()) {
            Channel channel = iterator.next();
            if (channel.isOpen() && channel.isActive()) {
                continue;
            }
            channel.close();
            iterator.remove();
        }
    }

}
